local jass = require 'jass.common'
local japi = require 'jass.japi'

local mt = ac.unit.__index

-- 定身
local function restriction_move(unit, flag)
	if flag then
		unit.move_speed_tag = 1
	else
		unit.move_speed_tag = 0
	end
	unit:add('移动速度', 0)
end

-- 缴械
local function restriction_attack(unit, flag)
	if flag then
		unit:add_ability 'Abun'
		unit:notify('单位-被缴械', unit)
	else
		unit:remove_ability 'Abun'
		unit:notify('单位-取消缴械', unit)
	end
end

-- 物免
local function restriction_attacked(unit, flag)
	if flag then
		jass.UnitAddType(unit.handle, jass.UNIT_TYPE_SAPPER)
	else
		jass.UnitRemoveType(unit.handle, jass.UNIT_TYPE_SAPPER)
	end
end

-- 禁魔
local function restriction_silence(self, flag)
	for skill in self:each_skill() do
		if (not skill.passive) and (not skill.physics) and not skill.is_order then
			skill:set_silent(flag)
		end
	end
end

-- 破坏
local function restriction_break(self, flag)
	if flag then
		for skill in self:each_skill() do
			if skill:is_visible() and (skill:get_type() == '英雄' or skill:get_type() == '通用') and not skill:has_mark '无法禁用' then
				if skill.passive then
					skill:disable()
					skill._restriction_break_flag = true
				end
			end
		end
	else
		for skill in self:each_skill() do
			if skill._restriction_break_flag then
				skill:enable()
				skill._restriction_break_flag = nil
			end
		end
	end
end

-- 锁闭
local function restriction_mute(self, flag)
	-- 打断物品技能
	if flag then
		self:add_restriction '禁魔'
		self:cast_stop()
		for _, item in ipairs(self:find_item()) do
			item:set_enable(false)
		end
	else
		self:remove_restriction '禁魔'
		for _, item in ipairs(self:find_item()) do
			item:set_enable(true)
		end
	end

end

-- 隐身
local function restriction_stealth(unit, flag)
	if flag then
		unit:add_ability 'A00E'
	else
		unit:remove_ability 'A00E'
	end
end

-- 隐藏
local function restriction_hide(unit, flag)
	jass.ShowUnit(unit.handle, not flag)
end

-- 隐藏模型
local function restriction_akari(unit, flag)
	if flag then
		jass.SetUnitFlyHeight(unit.handle, 999999, 0)
	else
		jass.SetUnitFlyHeight(unit.handle, unit.height, 0)
	end
end

-- 无视地形
local function restriction_fly(unit, flag)
	if flag then
		-- 飞行
		japi.EXSetUnitMoveType(unit.handle, 4)
	else
		if unit:has_restriction '幽灵' then
			-- 疾风步
			japi.EXSetUnitMoveType(unit.handle, 16)
		else
			japi.EXSetUnitMoveType(unit.handle, 2)
		end
		if unit:get_point():is_block() then
			-- TODO
			unit:blink(unit:get_point(), true, true)
		end
	end
end

-- 幽灵 关闭自身对他人的碰撞
local function restriction_collision(unit, flag)
    if unit:has_restriction '飞行' then
        return
    end
	if flag then
        japi.EXSetUnitMoveType(unit.handle, 16)
	else
        japi.EXSetUnitMoveType(unit.handle, 2)
	end
end

-- 晕眩
local function restriction_stun(unit, flag)
	if flag then
		unit:add_restriction '硬直'
	else
		unit:remove_restriction '硬直'
	end
end

-- 时停
local function restriction_time_pause(self, flag)
	if flag then
		self.last_pause_clock = ac.clock()
		self:add_restriction '硬直'
		-- self:pause_buff(true)
		-- self:pause_skill(true)
		-- self:pause_timer(true)
		ac.wait(0, function()
			self:set_animation_speed(0)
		end)
		self:set_facing(self:get_facing())
		self:notify('单位-时停开始', self)
	else
		self.paused_clock = self.paused_clock + ac.clock() - self.last_pause_clock
		self:set_animation_speed(1)
		-- self:pause_timer(false)
		-- self:pause_skill(false)
		-- self:pause_buff(false)
		self:remove_restriction '硬直'
		self:notify('单位-时停结束', self)
	end
end

-- 硬直
local function restriction_hard(unit, flag)
	if flag then
		if not unit._ignore_order_list then
			unit._ignore_order_list = {}
		end
		local order = unit._current_issue_order
		if order and unit._order_skills and unit._order_skills[order] then
			table.insert(unit._ignore_order_list, order)
		end
		japi.EXPauseUnit(unit.handle, true)
	else
		japi.EXPauseUnit(unit.handle, false)
		if unit._recover_skill then
			local skill = unit._recover_skill
			unit._recover_skill = nil
			skill[1]:cast_by_client(skill[2])
		end
	end
end

-- 吟唱
local function restriction_sing(unit, flag)
	if flag then
		-- if unit._restriction_hard_flag then
		-- 	japi.EXPauseUnit(unit.handle, false)
		-- 	unit._restriction_hard_flag = false
		-- end
		unit:add_ability 'A40J'
		
		--local handle = japi.EXGetUnitAbility(unit.handle, base.string2id('A40J'))
		--japi.EXSetAbilityDataReal(handle, 1, 0x6E, 0x01)
		--unit:set_ability_level('A40J', 2)
		--unit:set_ability_level('A40J', 1)

		local res = jass.IssueImmediateOrder(unit.handle, 'thunderclap')
		unit:issue_order('thunderclap')

		if unit._last_cast_animation then
			unit._hard_2_cast_animation_timer = ac.wait(20, function (t)
				unit:set_animation(unit._last_cast_animation)
				if unit._last_cast_animation and unit._last_cast_animation_loop_times and unit._last_cast_animation_loop_times > 0 then
					for i = 1, unit._last_cast_animation_loop_times do
						unit:add_animation(unit._last_cast_animation)
					end
				end
			end)
		end
	else
		--在释放技能的过程中，删除技能并不会打断当前命令，单位会站在原地不动，需要再发布一次命令来打断这个技能，具体的看地图怎么设计
		unit:remove_ability 'A40J'
		if unit:has_restriction '硬直' then
			-- if not unit._restriction_hard_flag then
			-- 	japi.EXPauseUnit(unit.handle, true)
			-- 	unit._restriction_hard_flag = true
			-- end
		end

		if unit._hard_2_cast_animation_timer and not unit._hard_2_cast_animation_timer.removed then
			unit._hard_2_cast_animation_timer:remove()
		end
	end
end

-- 无敌
local function restriction_god(self, flag)
	jass.SetUnitInvulnerable(self.handle, flag)
	if flag then
		self:add_restriction '物免'
	else
		self:remove_restriction '物免'
	end
end

-- 蝗虫
local function restriction_aloc(self, flag)
	if flag then
		self:add_ability 'Aloc'
	else
		self:remove_ability 'Aloc'
	end
end

-- 免死
local function restriction_dead()
end

-- 禁锢
local function restriction_constraint()
end

-- 禁止拾取物品
local function restriction_disable_pick_item()
end

-- 失控
local function restriction_out_of_control(self, flag)
	if flag then
		self:add_restriction '禁止拾取物品'
		for i, it in ipairs(self:find_item()) do
			jass.SetItemDroppable(it.handle, false)
		end
	else
		self:remove_restriction '禁止拾取物品'
		for i, it in ipairs(self:find_item()) do
			if it.can_discard or it.can_discard == nil then
				jass.SetItemDroppable(it.handle, true)
			end
		end
	end
end

-- 免疫负面效果
local function restriction_immune_debuff()
end

-- 禁止恢复
local function restriction_disable_recovery()
end

local restriction_type = {
	['硬直']		= restriction_hard,
	['吟唱']		= restriction_sing,
	['晕眩']		= restriction_stun,
	['禁锢']		= restriction_constraint,
	['定身']		= restriction_move,
	['缴械']		= restriction_attack,
	['物免']		= restriction_attacked,
	['禁魔']		= restriction_silence,
	['破坏']		= restriction_break,
	['锁闭']		= restriction_mute,
	['隐身']		= restriction_stealth,
	['隐藏']		= restriction_hide,		
	['隐藏模型']	= restriction_akari,	
	['飞行']		= restriction_fly,		
	['幽灵']		= restriction_collision,
	['时停']		= restriction_time_pause,
	['无敌']		= restriction_god,	
	['蝗虫']		= restriction_aloc,	
	['免死']		= restriction_dead,
	['失控']		= restriction_out_of_control,
	['禁止恢复']	= restriction_disable_recovery,
	
	['免疫负面效果']	= restriction_immune_debuff,

	['禁止拾取物品']	= restriction_disable_pick_item,
}

function mt:add_restriction(name)
	if not restriction_type[name] then
		log.error('错误的限制类型', name)
		return 0
	end
	local res = self['限制']
	if not res then
		res = {}
		self['限制'] = res
	end
	res[name] = (res[name] or 0) + 1
	if res[name] == 1 and restriction_type[name] then
		if not self.removed then 
			restriction_type[name](self, true)
		end 
	end
	return res[name]
end

function mt:remove_restriction(name)
	if not restriction_type[name] then
		log.error('错误的限制类型', name)
		return 0
	end
	local res = self['限制']
	if not res then
		res = {}
		self['限制'] = res
	end
	res[name] = (res[name] or 0) - 1
	if res[name] == 0 and restriction_type[name] then
		if not self.removed then 
			restriction_type[name](self, false)
		end 
	end
	if res[name] == -1 then
		log.error(self:get_name()..':计数错误', name)
	end
	return res[name]
end

function mt:has_restriction(name)
	if not restriction_type[name] then
		log.error('错误的限制类型', name)
		return false
	end
	local res = self['限制']
	if not res then
		res = {}
		self['限制'] = res
	end
	return res[name] and res[name] > 0
end



local baisc_order = {
    ['stop'] = true,
    ['attack'] = true,
    ['move'] = true,
    ['smart'] = true,
}
ac.game:event '单位-即将发布指令' (function (trigger, u, order, target, player_order, order_id)
	-- print( u, order, target, player_order, order_id)
	--屏蔽 吟唱 的指令
	if order == 852096 then
		return true
	end
	
    if not player_order then
        if order and baisc_order[order] then
            u._last_order = {
				order = order,
                target = target,
            }
		end
        return
    end
	
	if not u:has_restriction '失控' then
		return
	end

	if u._last_order then
		ac.wait(0, function ()
			trigger:disable()
			u:issue_order(u._last_order.order, u._last_order.target)
			trigger:enable()
		end)
	
		return true
	end

end)


return {
	restriction_type = restriction_type,
}